package com.bo.libnet.net;

import com.bo.libnet.util.Constants;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.orhanobut.logger.Logger;

import java.io.IOException;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import retrofit2.CallAdapter;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by bomei
 * date: 2018/1/30
 * 类描述：Retrofit 封装
 * 网络核心层。除在 Applciation中初始化，
 * 其他地方不调用，请求网络，请使用网络使用层
 * @see ApiCall 网络使用层
 */

public class ApiNet {
    
    private static ApiNet sInstance;
    private OkHttpClient mOkttpClient;
    private CallAdapter.Factory[] factories;
    private Interceptor[] interceptors,netInterceptors;
    private Retrofit mRetrofit;
    private HashMap<String,Object> apiSeverceMaps;

    private ApiNet(){
        apiSeverceMaps  = new HashMap<>();
    }
    public static ApiNet getInstance(){
        if(sInstance==null){
            synchronized(ApiNet.class){
                if(sInstance==null){
                    sInstance=new ApiNet();
                }
            }
        }
        return sInstance;
    }

    /**
     * 使用此类必须要 调用此方法初始化
     */
    public void init(){
        Gson gson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
                .create();

        mRetrofit = new Retrofit.Builder()
                .client(getOkCilent())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .baseUrl(Constants.NET_BASE_URL)
                .build();

        if (factories != null) {
            for (CallAdapter.Factory factory : factories) {
                mRetrofit.callAdapterFactories().add(factory);
            }
        }

    }


    /**
     *  在init() 调用之前有效
     */
    public ApiNet setOkHttpClient(OkHttpClient client){
        mOkttpClient = client;
        return this;
    }

    /**
     *  在init() 调用之前有效
     */
    public ApiNet addCallAdapterFactory(CallAdapter.Factory... factories){
        this.factories = factories;
        return this;
    }

    /**
      *  在init() 调用之前有效
     *   应用拦截器 添加
     *   应用拦截器：主要用于设置公共参数，头信息，设置缓存策略，日志拦截等,有点类似Retrofit的Converter
     */
    public ApiNet addOkClientInterceptors(Interceptor... interceptors){
        this.interceptors = interceptors;
        return this;
    }


    /**
      *  在init() 调用之前有效
     *  网络拦截器 添加
     * 网络拦截器：主要用于重试或重写
     */
    public ApiNet addOkClientNetInterceptors(Interceptor... netInterceptors){
        this.netInterceptors = netInterceptors;
        return this;
    }

    /**
     * 获取OkCilent
     */
    private OkHttpClient getOkCilent(){
        OkHttpClient deafuleOkHttpClient = new OkHttpClient.Builder()
                .retryOnConnectionFailure(true)
                .connectTimeout(Constants.NET_CONNECT_TIME_OUT, TimeUnit.SECONDS)
                .readTimeout(Constants.NET_READ_TIME_OUT, TimeUnit.SECONDS)
                .writeTimeout(Constants.NET_WRITE_TIME_OUT, TimeUnit.SECONDS)
                .addInterceptor(new LoggerInteceptor())
                .build();

        if (interceptors != null) {
            for (Interceptor interceptor : interceptors) {
                deafuleOkHttpClient.interceptors().add(interceptor);
            }
        }
        if (netInterceptors != null) {
            for (Interceptor netInterceptor : netInterceptors) {
                deafuleOkHttpClient.networkInterceptors().add(netInterceptor);
            }
        }
        return mOkttpClient == null?deafuleOkHttpClient:mOkttpClient;
    }

    /**
     * 获取 retrofit实例
     */
    private Retrofit getmRetrofit(){
        if(mRetrofit == null){
            throw new NullPointerException("mRetrofit 为空，请先调用init()初始化方法");
        }
        return mRetrofit;
    }


    protected  <T> T getApiServce(Class<T> apiSeverce){
        Object object = apiSeverceMaps.get(apiSeverce.getSimpleName());
        if (object != null) {
            return (T)object;
        }else {
            T t = ApiNet.getInstance().getmRetrofit().create(apiSeverce);
            apiSeverceMaps.put(apiSeverce.getSimpleName(),t);
            return t;
        }
    }

    protected void clearApiSeverceMaps(){
        apiSeverceMaps.clear();
    }

    /**
     * 应用拦截器：Logger日志拦截器
     */
    private class LoggerInteceptor implements Interceptor{
        @Override
        public Response intercept(Chain chain) throws IOException {

            Request request = chain.request();
            long currentTime = System.nanoTime();
            Logger.v("Api请求->time:"+currentTime+"\n"+request.body()+"\n"+chain.connection()+"\n"+request.url()+"\n"+request.headers());

            Response response = chain.proceed(request);
            ResponseBody responseBody = response.peekBody(1024 * 1024 * 2);
            Logger.v("Api响应->time:"+currentTime,response.body(),response.request().url(),response.headers());
            Logger.json(new String(responseBody.bytes()));
            return response;
        }
    }


}
